﻿using SuperSocket.SocketBase;
using SuperSocket.SocketBase.Config;
using SuperSocket.SocketBase.Protocol;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;

namespace VswService_V7.Sok
{
    public class MyServer
    {
        //SERVER base information
        public bool Status { get; set; }
        public string ServerIP { get; set; }
        public int ServerPort { get; set; }


        private SortedList<string, VswSession> sessionList;
        private VswTcpServer appServer;
        //public MessageHandler messageHandler;
        //一.
        public event EventHandler<SessionListChangedEventArgs> SessionChanged;

        public MyServer(string IP, int port)
        {
            appServer = new VswTcpServer();
            sessionList = new SortedList<string, VswSession>();
            Status = false;
            ServerIP = IP;
            ServerPort = port;
        }

        public MyServer(int port)
        {
            appServer = new VswTcpServer();
            sessionList = new SortedList<string, VswSession>();
            Status = false;
            IPAddress[] iPAddresses = Dns.GetHostEntry(Dns.GetHostName()).AddressList;
            string ip = "";
            for (int i = 0; i < iPAddresses.Length; i++)
            {
                if (iPAddresses[i].AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
                {
                    ip = iPAddresses[i].ToString();
                    break;
                }
            }
            ServerIP = ip;
            ServerPort = port;
        }

        // -1 address format error!
        // -2 Failed to open the listening port!
        // -3 Server failed to start!
        // 1 The server started successfully!
        public int Start()
        {
            try
            {
                IPAddress ip = IPAddress.Parse(ServerIP);
            }
            catch
            {
                return -1;
            }
            ServerConfig serverConfig = new ServerConfig();
			//serverConfig.TextEncoding = ASCIIEncoding.ASCII.ToString();
			serverConfig.TextEncoding = "UTF-8";
			serverConfig.Ip = ServerIP;
            serverConfig.Port = ServerPort;

			//if (!appServer.Setup(serverConfig.Port))
			//    return -2;
			if (!appServer.Setup(serverConfig))
				return -2;

			if (!appServer.Start())
                return -3;

            //Client connection event
            appServer.NewSessionConnected += AppServer_NewSessionConnected;

            //Accept message This event conflicts with Commandexcute, Commandexcute does not execute when this event is enabled:https://www.cnblogs.com/qq247039968/p/7839447.html 但是commandfileter还是起作用的
            //appServer.NewRequestReceived += AppServer_NewRequestReceived;

            //Client closed
            appServer.SessionClosed += AppServer_SessionClosed;
            Status = true;
            return 1;
        }


        private void AppServer_NewSessionConnected(VswSession session)
        {
            string sessionIP = string.Format("{0}:{1}", session.RemoteEndPoint.Address, session.RemoteEndPoint.Port);
            session.Name = sessionIP;
            //默认操作员登陆
            session.UserLevel = 0;
            sessionList.Add(sessionIP, session);
            //三.
            SessionChanged?.Invoke(this, new SessionListChangedEventArgs(session.Name, true, session.LastActiveTime));

            //先运行AppServer_NewSessionConnected 再运行OnSessionStarted
            //session.Send("new comming!!");
        }


        private void AppServer_SessionClosed(VswSession session, CloseReason value)
        {
            sessionList.Remove(session.Name);
            //三.
            SessionChanged?.Invoke(this, new SessionListChangedEventArgs(session.Name, false, session.LastActiveTime));
        }

        //不用
        private void AppServer_NewRequestReceived(VswSession session, SuperSocket.SocketBase.Protocol.StringRequestInfo requestInfo)
        {
            string body = requestInfo.Body;
            session.Send(body);
        }

        public void Stop()
        {
            appServer.Stop();
            Status = false;
        }

    }

    //二.
    public class SessionListChangedEventArgs : EventArgs
    {
        public string SessionAdr { get; }
        public bool Action { get; }
        public DateTime LastActive { get; }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="sessionAdr"></param>
        /// <param name="action">true=add;false=remove</param>
        public SessionListChangedEventArgs(string sessionAdr, bool action, DateTime lastactive)
        {
            SessionAdr = sessionAdr;
            Action = action;
            LastActive = lastactive;
        }
    }
}
